home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / tutorials / custEducation / opengl1 / answers / animate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  13.3 KB  |  556 lines

  1. /*
  2.  * Copyright 1993, 1996, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. /* animate.c - open a window and clear the background.
  19.  *    Set up callbacks to handle keyboard input.
  20.  *      Model some objects.  Use perspective projection.
  21.  *    Use independent modeling transformations to position objects.
  22.  *    Added reshape callback to reset the viewport and viewing volume.
  23.  *    Add depth buffering.
  24.  *    Add a viewing transformation and control it using mouse input.
  25.  *    Add continuous animation and a menu to control it.
  26.  *
  27.  *    F1 key            - print help information
  28.  *    Right Mouse Button    - popup menu
  29.  *    Left Arrow Key        - move the reference point to the left
  30.  *    Right Arrow Key        - move the reference point to the right
  31.  *    Up Arrow Key        - move the reference point up
  32.  *    Down Arrow Key        - move the reference point down
  33.  *    <f> key            - toggle front/back face culling
  34.  *    <s> key            - toggle smooth/flat shading
  35.  *    SPACE key        - generates a random background color
  36.  *    Escape Key        - exit program
  37.  */
  38. #include <GL/gl.h>
  39. #include <GL/glu.h>
  40. #include <GL/glut.h>
  41.  
  42. #include <stdio.h>
  43. #include <math.h>
  44.  
  45. /* Function Prototypes */
  46.  
  47. GLvoid initgfx( GLvoid );
  48. GLvoid keyboard( GLubyte, GLint, GLint );
  49. GLvoid specialkeys( GLint, GLint, GLint );
  50. GLvoid reshape( GLsizei, GLsizei );
  51. GLvoid animate( GLvoid );
  52. GLvoid visibility( GLint );
  53. GLvoid drawScene( GLvoid );
  54. GLvoid menuFunc( GLint );
  55.  
  56. void initGround( GLvoid );
  57.  
  58. void checkError( char * );
  59. void printHelp( char * );
  60.  
  61. /* Global Variables */
  62.  
  63. static GLdouble        xRef = 0.0, yRef = 0.0;
  64.  
  65. static GLfloat        sunPosition = 2.5;
  66.  
  67. static GLfloat         green[] = { 0.0, 1.0, 0.0 };
  68. static GLfloat         darkgreen[] = { 0.0, 0.25, 0.0 };
  69. static GLfloat         red[] = { 1.0, 0.0, 0.0 };
  70. static GLfloat         magenta[] = { 1.0, 0.0, 1.0 };
  71. static GLfloat         yellow[] = { 1.0, 1.0, 0.0 };
  72. static GLfloat         blue[] = { 0.0, 0.0, 1.0 };
  73.  
  74. static GLfloat         white[] = { 1.0, 1.0, 1.0, 1.0 };
  75. static GLfloat         black[] = { 0.0, 0.0, 0.0, 0.0 };
  76.  
  77. static char *progname; 
  78.  
  79. /* Global Definitions */
  80.  
  81. #define KEY_ESC    27    /* ascii value for the escape key */
  82.  
  83. /* menu options */
  84. #define MENU_ANIMATE    1    /* animation control option */
  85. #define MENU_EXIT    2    /* exit option */
  86.  
  87. #define GRIDPOINTS    41    /* number of vertices in ground mesh */
  88.  
  89. static GLfloat         groundMesh[GRIDPOINTS][GRIDPOINTS][3] = { 0 };
  90.  
  91. static GLboolean     animateFlag = GL_TRUE;
  92.  
  93. void
  94. main( int argc, char *argv[] )
  95. {
  96.     GLsizei width, height;
  97.  
  98.     glutInit( &argc, argv );
  99.  
  100.     /* create a window that is 1/4 the size of the screen,
  101.      * and position it in the middle of the screen.
  102.      */
  103.     width = glutGet( GLUT_SCREEN_WIDTH ); 
  104.     height = glutGet( GLUT_SCREEN_HEIGHT );
  105.     glutInitWindowPosition( width / 4, height / 4 );
  106.     glutInitWindowSize( width / 2, height / 2 );
  107.     glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
  108.     glutCreateWindow( argv[0] );
  109.  
  110.     initgfx();
  111.  
  112.     glutIdleFunc( animate );
  113.     glutVisibilityFunc( visibility );
  114.     glutReshapeFunc( reshape );
  115.     glutKeyboardFunc( keyboard );
  116.     glutSpecialFunc( specialkeys );
  117.     glutDisplayFunc( drawScene ); 
  118.  
  119.     /* create menu and add menu options */
  120.     glutCreateMenu( menuFunc );
  121.     glutAddMenuEntry( "Stop Animation", MENU_ANIMATE );
  122.     glutAddMenuEntry( "Exit", MENU_EXIT );
  123.     glutAttachMenu( GLUT_RIGHT_BUTTON );
  124.  
  125.     progname = argv[0];
  126.  
  127.     printHelp( progname );
  128.  
  129.     glutMainLoop();
  130. }
  131.  
  132. void
  133. printHelp( char *progname )
  134. {
  135.     fprintf(stdout, 
  136.         "\n%s - create a scene and handle resizing\n\n"
  137.         "F1 key        - print help information\n"
  138.         "Left Arrow Key        - move reference point to the left\n"
  139.         "Right Arrow Key    - move reference point to the right\n"
  140.         "Up Arrow Key        - move reference point up\n"
  141.         "Down Arrow Key        - move reference point down\n"
  142.         "SPACE Key    - generates a random background color\n"
  143.         "<f> key        - toggle front/back face culling\n"
  144.         "<s> key        - toggle smooth/flat shading\n"
  145.         "Escape Key    - exit the program\n\n",
  146.         progname);
  147. }
  148.  
  149. GLvoid
  150. initgfx( GLvoid )
  151. {
  152.     /* set clear color to blue */
  153.     glClearColor( 0.0, 0.0, 1.0, 1.0 );
  154.  
  155.     /* enable the depth buffer */
  156.     glEnable( GL_DEPTH_TEST );
  157.  
  158.     /* enable the face culling */
  159.     glEnable( GL_CULL_FACE );
  160.  
  161.     initGround();
  162.  
  163.     /* Turn on the default light */
  164.     glEnable( GL_LIGHT0 );
  165.     glEnable( GL_LIGHTING );
  166.  
  167.     /* have OpenGL automatically normalize the normals,
  168.      * since we have lighting turned on and are scaling
  169.       */
  170.     glEnable( GL_NORMALIZE );
  171.  
  172.     /* Enable fast material changes for diffuse material */
  173.     glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
  174.     glEnable( GL_COLOR_MATERIAL );
  175. }
  176.  
  177. GLvoid 
  178. reshape( GLsizei width, GLsizei height )
  179. {
  180.     GLdouble    aspect;
  181.  
  182.     glViewport( 0, 0, width, height );
  183.  
  184.     /* compute aspect ratio */
  185.     aspect = (GLdouble) width / (GLdouble) height;
  186.  
  187.     glMatrixMode( GL_PROJECTION );
  188.  
  189.     /* Reset world coordinates first ... */
  190.     glLoadIdentity();
  191.  
  192.     /* Reset the viewing volume based on the new aspect ratio */
  193.     gluPerspective( 45.0, aspect, 3.0, 7.0 );
  194.  
  195.     glMatrixMode( GL_MODELVIEW );
  196. }
  197.  
  198. void 
  199. checkError( char *label )
  200. {
  201.     GLenum error;
  202.     while ( (error = glGetError()) != GL_NO_ERROR )
  203.         printf( "%s: %s\n", label, gluErrorString(error) );
  204. }
  205.  
  206. GLvoid 
  207. keyboard( GLubyte key, GLint x, GLint y )
  208. {
  209.     static GLboolean flat = GL_FALSE;
  210.     static GLboolean cullFront = GL_FALSE;
  211.  
  212.     switch (key) {
  213.     case ' ':    /* SPACE key */
  214.         /* generate a random background color */
  215.         glClearColor( drand48(), drand48(), drand48(), 1.0 ); 
  216.         glutPostRedisplay();
  217.         break;
  218.     case 'f':    /* f key */
  219.         /* toggle between back and front face culling */
  220.         cullFront = !cullFront;
  221.         if (cullFront) {
  222.             glCullFace( GL_FRONT );
  223.             printf("Culling FRONT faces\n");
  224.         } else { 
  225.             glCullFace( GL_BACK );
  226.             printf("Culling BACK faces\n");
  227.         }
  228.         glutPostRedisplay();
  229.         break;
  230.     case 's':    /* s key */
  231.         /* toggle between smooth and flat shading */
  232.         flat = !flat;
  233.         if (flat)
  234.             glShadeModel( GL_FLAT );
  235.         else 
  236.             glShadeModel( GL_SMOOTH );
  237.         glutPostRedisplay();
  238.         break;
  239.     case KEY_ESC:    /* Exit when the Escape key is pressed */
  240.         exit(0);
  241.     }
  242. }
  243.  
  244. GLvoid 
  245. specialkeys( GLint key, GLint x, GLint y )
  246. {
  247.     switch (key) {
  248.     case GLUT_KEY_F1:    /* Function key #1 */
  249.         /* print help information */
  250.         printHelp( progname );
  251.         break;
  252.  
  253.     case GLUT_KEY_LEFT:    /* move reference point to the left */
  254.         xRef -= 0.5;
  255.         if (xRef < -4.0) xRef = -4.0;
  256.         glutPostRedisplay();
  257.          break;
  258.  
  259.     case GLUT_KEY_RIGHT:    /* move reference point to the right */
  260.         xRef += 0.5;
  261.         if (xRef > 4.0) xRef = 4.0;
  262.         glutPostRedisplay();
  263.         break;
  264.  
  265.     case GLUT_KEY_UP:    /* move reference point up */
  266.         yRef += 0.5;
  267.         if (yRef > 3.0) yRef = 3.0;
  268.         glutPostRedisplay();
  269.         break;
  270.  
  271.     case GLUT_KEY_DOWN:    /* move reference point down */
  272.         yRef -= 0.5;
  273.         if (yRef < -3.0) yRef = -3.0;
  274.         glutPostRedisplay();
  275.         break;
  276.     }
  277. }
  278.  
  279. GLvoid 
  280. animate( GLvoid )
  281. {
  282.     /* update the position of the sun */
  283.     sunPosition -= 0.01;
  284.     if (sunPosition < -3.0) sunPosition = 2.5;
  285.  
  286.     /* Tell GLUT to redraw the scene */
  287.     glutPostRedisplay();
  288. }
  289.  
  290. GLvoid
  291. visibility( int state ) 
  292. {
  293.     if (state == GLUT_VISIBLE && animateFlag) {
  294.         glutIdleFunc( animate );
  295.     } else {
  296.         glutIdleFunc( NULL );
  297.     }
  298. }
  299.  
  300. GLvoid
  301. menuFunc( int value )
  302. {
  303.     switch (value) {
  304.     case MENU_ANIMATE:
  305.         animateFlag = !animateFlag;
  306.         if (animateFlag) {
  307.             glutIdleFunc( animate );
  308.             glutChangeToMenuEntry( MENU_ANIMATE, "Stop Animation",
  309.                         MENU_ANIMATE );
  310.         } else {
  311.             glutIdleFunc( NULL );
  312.             glutChangeToMenuEntry( MENU_ANIMATE, "Start Animation",
  313.                         MENU_ANIMATE );
  314.         }
  315.         break;
  316.     case MENU_EXIT:
  317.         exit(0);
  318.     }
  319. }
  320.  
  321. void
  322. initGround( void )
  323. {
  324.     int i, j;
  325.     GLfloat     x, y, spacing;
  326.  
  327.     /* Create a flat grid composed of points with the z value = 0 */
  328.     
  329.     /* spacing = distance between adjacent grid points in x and y */
  330.     spacing = 2.0 / (float)(GRIDPOINTS - 1);
  331.  
  332.     /* x and z range from -1.0 to 1.0 by spacing interval */
  333.     for ( x = -1.0, i = 0; i < GRIDPOINTS; x += spacing, i++ ) {
  334.         for ( y = -1.0, j = 0; j < GRIDPOINTS; y += spacing, j++ ) {
  335.             groundMesh[i][j][0] = x;
  336.             groundMesh[i][j][1] = y;
  337.             groundMesh[i][j][2] = 0.0;
  338.         }
  339.     }
  340. }
  341.  
  342. GLvoid
  343. drawGround( GLvoid )
  344. {
  345.     register int i, j;
  346.  
  347.     glNormal3f( 0.0, 0.0, 1.0 );
  348.     
  349.     /* Draw quad strips connecting grid points. 
  350.      * Grid is drawn column by column, 
  351.      * where each column is one quad strip.
  352.      * Every pair of vertices after first two vertices
  353.      * adds a new quad to the strip.
  354.      */
  355.     for ( i = 0; i < (GRIDPOINTS - 1); i++ ) {
  356.         glBegin( GL_QUAD_STRIP );
  357.         for ( j = 0; j < (GRIDPOINTS); j++ ) {
  358.             glColor3f( 0.0, 1.0 - (GLfloat) j/GRIDPOINTS, 0.0 );
  359.             glVertex3fv( &groundMesh[i][j][0] );
  360.             glVertex3fv( &groundMesh[i + 1][j][0] );
  361.         }
  362.         glEnd();
  363.     }
  364. }
  365.  
  366. GLvoid
  367. drawWindow()
  368. {
  369.     /* window */
  370.     static GLfloat v0[] = { 0.0, 0.4 };
  371.     static GLfloat v1[] = { 0.0, 0.0 };
  372.     static GLfloat v2[] = { 0.1, 0.4 };
  373.     static GLfloat v3[] = { 0.1, 0.0 };
  374.     static GLfloat v4[] = { 0.2, 0.4 };
  375.     static GLfloat v5[] = { 0.2, 0.0 };
  376.  
  377.     /* draw 2 quadrilateral strip to make a window */
  378.     glNormal3f( 0.0, 0.0, 1.0 );
  379.     glBegin( GL_QUAD_STRIP );
  380.         glColor3f( 1.0, 0.0, 0.0 );
  381.         glVertex2fv (v0);
  382.         glColor3f( 0.9, 0.0, 1.0 );
  383.         glVertex2fv (v1);
  384.         glColor3f( 0.8, 0.1, 0.0 );
  385.         glVertex2fv (v2);
  386.         glColor3f( 0.7, 0.2, 1.0 );
  387.         glVertex2fv (v3);
  388.         glColor3f( 0.6, 0.3, 0.0 );
  389.         glVertex2fv (v4);
  390.         glColor3f( 0.5, 0.4, 1.0 );
  391.         glVertex2fv (v5);
  392.         glColor3f( 0.4, 0.5, 0.0 );
  393.     glEnd();
  394. }
  395.  
  396. /* draw a "circle" using a triangle fan; set the
  397.  * center of the circle to white, and the outside
  398.  * to the color passed in
  399.  */
  400. GLvoid
  401. drawFan( GLfloat *color )
  402. {
  403.     /* Draw a triangle fan centered at the current coordinate
  404.      * system origin 
  405.      */
  406.     glNormal3f( 0.0, 0.0, 1.0 );
  407.     glBegin( GL_TRIANGLE_FAN );
  408.         glColor3f( 1.0, 1.0, 1.0 );
  409.         glVertex2f( 0.0, 0.0 );
  410.         glColor3fv( color );
  411.         glVertex2f( 0.0, -0.2 );
  412.         glVertex2f( 0.2, -0.1 );
  413.         glVertex2f( 0.2, 0.1 );
  414.         glVertex2f( 0.0, 0.2 );
  415.         glVertex2f( -0.2, 0.1 );
  416.         glVertex2f( -0.2, -0.1 );
  417.         glVertex2f( 0.0, -0.2 );
  418.     glEnd();
  419. }
  420.  
  421. /* draw a flower with the base of the stem 
  422.  * at the current location 
  423.  */
  424. GLvoid
  425. drawFlower( GLfloat *color )
  426. {
  427.     /* draw the stem with 2 leaves */
  428.     glColor3fv( darkgreen );
  429.     glNormal3f( 0.0, 0.0, 1.0 );
  430.     glBegin( GL_LINES );
  431.         glVertex2f( 0.0, 0.0 );         /* stem */
  432.         glVertex2f( 0.0, 0.25 );
  433.         glVertex2f( 0.0, 0.1 );         /* leaf */
  434.         glVertex2f( 0.05, 0.15 ); 
  435.         glVertex2f( 0.0, 0.05 );     /* leaf */
  436.         glVertex2f( -0.05, 0.2 );
  437.     glEnd();
  438.  
  439.     glPushMatrix();
  440.         /* move to the top of the stem */
  441.         glTranslatef( 0.0, 0.25, 0.0 );
  442.  
  443.         /* use a scaled triangle fan for the flower head */
  444.         glScalef( 0.1, 0.1, 1.0 );
  445.         drawFan( color );  
  446.     glPopMatrix();
  447. }
  448.  
  449. /* draw a house centered at the current origin;
  450.  * the bounding box for the house is 1.0 x 2.0 units
  451.  */
  452. GLvoid
  453. drawHouse()
  454. {
  455.     /* draw a 3D house */
  456.     glColor3f( 1.0, 1.0, 1.0 ); /* white */
  457.     SolidBox( 1.0, 1.5, 1.0 );
  458.  
  459.     glPushMatrix();
  460.         /* move to the peak of the roof */
  461.         glTranslatef( 0.0, 1.25, 0.0 );
  462.  
  463.         /* draw a triangle fan for the roof */
  464.         glColor3f( 0.0, 0.0, 0.0 ); /* black */
  465.         glNormal3f( 0.0, 1.0, 1.0 );
  466.         glBegin( GL_TRIANGLE_FAN );
  467.             glVertex3f( 0.0, 0.0, 0.0 ); /* peak */
  468.             glVertex3f( -0.5, -0.5, 0.5 ); /* front left */
  469.             glVertex3f( 0.5, -0.5, 0.5 ); /* front right */
  470.             glVertex3f( 0.5, -0.5, -0.5 ); /* back right */
  471.             glVertex3f( -0.5, -0.5, -0.5 ); /* back left */
  472.             glVertex3f( -0.5, -0.5, 0.5 ); /* front left */
  473.         glEnd();
  474.     glPopMatrix();
  475.  
  476.     glPushMatrix();
  477.         /* move to just in front of the house */
  478.         glTranslatef( 0.0, 0.0, 0.50001 );
  479.  
  480.         /* draw the door */
  481.         glColor3f( 0.5, 0.2, 0.1 ); /* brown */
  482.         glNormal3f( 0.0, 0.0, 1.0 );
  483.         glRectf( -0.2, -0.75, 0.2, 0.0 );
  484.  
  485.         glPushMatrix();
  486.             /* move to the location for the left window */
  487.             glTranslatef( -0.4, 0.2, 0.0 );
  488.             drawWindow();
  489.         glPopMatrix();
  490.  
  491.         glPushMatrix();
  492.             /* move to the location for the right window */
  493.             glTranslatef( 0.2, 0.2, 0.0 );
  494.             drawWindow();
  495.         glPopMatrix();
  496.     glPopMatrix();
  497. }
  498.  
  499. GLvoid
  500. drawScene( GLvoid )
  501. {
  502.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  503.  
  504.     glPushMatrix();
  505.  
  506.         /* Move the reference point */
  507.         gluLookAt( 0.0, 0.0, 4.0, xRef, yRef, 0.0, 0.0, 1.0, 0.0 );
  508.  
  509.         /* draw the ground as a quad mesh so that it will
  510.          * be lit properly
  511.          */
  512.         glPushMatrix();
  513.             glTranslatef( 0.0, -1.0, 0.0 );
  514.             glRotatef( -45.0, 1.0, 0.0, 0.0 );
  515.             glScalef( 3.0, 1.0, 1.0 );
  516.             drawGround();
  517.         glPopMatrix();
  518.  
  519.         /* draw the house */
  520.         glPushMatrix();
  521.             /* move to where the center of the house should be */
  522.             glTranslatef( -0.5, 0.0, 0.0 );
  523.  
  524.             /* shrink the house slightly */
  525.             glScalef( 0.7, 0.7, 0.7 );
  526.             drawHouse();
  527.         glPopMatrix();
  528.  
  529.         /* draw the sun */
  530.         glPushMatrix();
  531.             /* move to the location of the sun */
  532.             glTranslatef( sunPosition, 2.0, -1.5 );
  533.             glColor3fv( yellow );
  534.             glutSolidSphere( 0.2, 8, 15 );
  535.         glPopMatrix();
  536.  
  537.         /* draw several tulips in the foreground */
  538.         glPushMatrix();
  539.             glTranslatef( 1.0, -1.0, 1.0 );
  540.             drawFlower( red );
  541.             glTranslatef( 0.0, 0.0, -0.5 );
  542.             drawFlower( yellow );
  543.         glPopMatrix();
  544.         glPushMatrix();
  545.             glTranslatef( -1.0, -1.0, 1.0 );
  546.             drawFlower( blue );
  547.             glTranslatef( 0.0, 0.0, -0.5 );
  548.             drawFlower( magenta );
  549.         glPopMatrix();
  550.  
  551.     glPopMatrix();
  552.  
  553.     checkError( "drawScene" );
  554.     glutSwapBuffers();
  555. }
  556.